package server.command.list;

import java.lang.reflect.InvocationTargetException;
import java.util.Calendar;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;

import communication.exception.ResultException;
import communication.exception.VerifyParameterException;

import server.command.AnalysisCommand;
import server.command.Command;
import server.core.base.Airport;
import server.core.base.Flight;
import server.core.dao.DaoFactory;
import server.core.dao.MemoryDAO;
import server.core.manager.Guest;
import server.core.manager.Manager;

public class SearchFlight implements Command {
	private AnalysisCommand parsing;
	@Override
	public Collection<Object> execute() throws ResultException {
		Collection<Object> result=new LinkedList<Object>();
		Collection<Flight> flightsDirect = null;
		Collection<Flight> flightsIndirect = null;
		
			try {
				flightsDirect=((Guest) getManager().getConstructor(parsing.getTypeOfDao().getClass()).newInstance(parsing.getTypeOfDao())).searchFlight(
							(Airport) parsing.getArgsMap().get("FROMPORT"),
							(Airport) parsing.getArgsMap().get("TOPORT"),
							(Calendar) parsing.getArgsMap().get("FROMDATE"),
							(Calendar) parsing.getArgsMap().get("TODATE")
							);
			} catch (InstantiationException | IllegalAccessException
					| IllegalArgumentException | InvocationTargetException
					| NoSuchMethodException | SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				flightsIndirect=((Guest) getManager().getConstructor(parsing.getTypeOfDao().getClass()).newInstance(parsing.getTypeOfDao())).getIndirectFlights(
						(Airport) parsing.getArgsMap().get("FROMPORT"),
						(Airport) parsing.getArgsMap().get("TOPORT"),
						(Calendar) parsing.getArgsMap().get("FROMDATE"),
						(Calendar) parsing.getArgsMap().get("TODATE")
						);
			} catch (InstantiationException | IllegalAccessException
					| IllegalArgumentException | InvocationTargetException
					| NoSuchMethodException | SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			if(flightsDirect==null & flightsIndirect!=null)
				result.addAll(flightsIndirect);
			else if(flightsIndirect==null & flightsDirect!=null)
				result.addAll(flightsDirect);
			else if(flightsIndirect==null & flightsDirect==null)
				throw new ResultException("There is no flight found!");
			else{
				flightsDirect.addAll(flightsIndirect);
				result.addAll(flightsDirect);
			}
			result.add("Found: "+result.size());
			return result;
	}

	@Override
	public void verifyParam(AnalysisCommand parsing) throws VerifyParameterException {
		Iterator<?> itr;
		this.parsing=parsing;
		for(String key:AnalysisCommand.paramAirport){
			if(parsing.getParamMap().containsKey(key)){
				itr=((MemoryDAO) DaoFactory.getDao(parsing.getTypeOfDao())).getEntityMap(Airport.class).values().iterator();
				while(itr.hasNext()){
					Airport port=(Airport) itr.next();
					if(port.getTitle().equalsIgnoreCase(parsing.getParamMap().get(key)))
						parsing.getArgsMap().put(key, port);
				}
				if(! parsing.getArgsMap().containsKey(key))
					throw new VerifyParameterException("Unknown airport`s code in #"+key);
			}
			else
//				this.argsMap.put(key, null);
				throw new VerifyParameterException(
						"Parameter is missing #"+key);
		}
		for(String key:AnalysisCommand.paramBetweenDate){
			if(parsing.getParamMap().containsKey(key))
				parsing.getArgsMap().put(key,parsing.changeStringIntoDate(parsing.getParamMap().get(key)).getDate());
			else
				throw new VerifyParameterException("Parameter is missing #"+key);
		}

	}

	@Override
	public String help() {
		return " fromPort= toPort= fromDate= toDate=";
		
	}

	@Override
	public Class<? extends Manager> getManager() {
		return Guest.class;
	}

	@Override
	public void exit() {
		// TODO Auto-generated method stub
		
	}

}
